/*
 * SharpnessDialog.java
 *
 * Created on Sep 19, 2011, 8:00:06 PM
 */
package com.photoexpert;

import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

/**
 *
 * @author PANYIXIN
 */
class SharpnessDialog extends javax.swing.JDialog {

    SharpnessDialog() {
        super(App.Instance(), true);
        initComponents();
        setLocation(200, 200);
        _slider.setValue(0);
        _width.setSelectedIndex(0);
        ((PreviewPane)_previewPane).setOp(null);
        setVisible(true);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        _slider = new javax.swing.JSlider();
        _previewLabel = new javax.swing.JLabel();
        _previewPane = PreviewPane.CreateInstance();
        _cancel = new javax.swing.JButton();
        _ok = new javax.swing.JButton();
        _widthLabel = new javax.swing.JLabel();
        _width = new javax.swing.JComboBox();
        _depthLabel = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Sharpness / Blur");
        setModal(true);
        setResizable(false);

        _slider.setMajorTickSpacing(2);
        _slider.setMaximum(10);
        _slider.setMinimum(-10);
        _slider.setMinorTickSpacing(1);
        _slider.setPaintLabels(true);
        _slider.setPaintTicks(true);
        _slider.setValue(0);
        _slider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                _sliderStateChanged(evt);
            }
        });

        _previewLabel.setText("Preview:");

        _previewPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        _previewPane.setPreferredSize(new java.awt.Dimension(252, 192));

        javax.swing.GroupLayout _previewPaneLayout = new javax.swing.GroupLayout(_previewPane);
        _previewPane.setLayout(_previewPaneLayout);
        _previewPaneLayout.setHorizontalGroup(
            _previewPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 250, Short.MAX_VALUE)
        );
        _previewPaneLayout.setVerticalGroup(
            _previewPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 190, Short.MAX_VALUE)
        );

        _cancel.setText("Cancel");
        _cancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _cancelActionPerformed(evt);
            }
        });

        _ok.setText("OK");
        _ok.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _okActionPerformed(evt);
            }
        });

        _widthLabel.setText("Width:");

        _width.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }));
        _width.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _widthActionPerformed(evt);
            }
        });

        _depthLabel.setText("Depth:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(_previewPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(_ok, javax.swing.GroupLayout.DEFAULT_SIZE, 67, Short.MAX_VALUE)
                            .addComponent(_cancel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(_widthLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(_width, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(_depthLabel)
                    .addComponent(_slider, javax.swing.GroupLayout.DEFAULT_SIZE, 326, Short.MAX_VALUE)
                    .addComponent(_previewLabel))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(_widthLabel)
                    .addComponent(_width, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(_depthLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(_slider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(_previewLabel)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_ok)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_cancel))
                    .addGroup(layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(_previewPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private ConvolveOp calculateOp() {
        int value = _slider.getValue();
        if(value == 0)
            return null;
        int width = Integer.parseInt((String)(_width .getSelectedItem()));
        float[][] data = new float[width * 2 + 1][width * 2 + 1];
        float delta = 0;
        if(value > 0)
            delta = value - 1;
        else {
           double d = Math.pow(2, -value);
           delta = (float)(0f - (1f - 1f / d));
        }
        data[width][width] = 1 + delta;
        float remainder = -delta;
        for(int i = 1; i <= width; ++i) {
            // for each round, we distribute half of the remainder to 8*i points
            remainder /= 2;
            float distribute = remainder / (8 * i);
            for(int j = -i; j <= i; ++j) {
                data[width + j][width - i] = distribute;
                data[width + j][width + i] = distribute;
            }
            for(int j = -i + 1; j <= i - 1; ++j) {
                data[width - i][width + j] = distribute;
                data[width + i][width + j] = distribute;
            }
        }
        // for remainder, distribute to the nearest 4 points
        float distribute = remainder / 4;
        data[width - 1][width] += distribute;
        data[width + 1][width] += distribute;
        data[width][width - 1] += distribute;
        data[width][width + 1] += distribute;
        // now create 1 dimension array for Kernal
        int dimension = width * 2 + 1;
        float kernal[] = new float[dimension * dimension];
        for(int n = 0; n < dimension; ++n)
            for(int m = 0; m < dimension; ++m)
                kernal[n * dimension + m] = data[n][m];
        _op = new ConvolveOp(new Kernel(dimension, dimension, kernal), ConvolveOp.EDGE_NO_OP, null);
        return _op;
    }

    private void _sliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event__sliderStateChanged
        _op = calculateOp();
        ((PreviewPane)_previewPane).setOp(_op);
    }//GEN-LAST:event__sliderStateChanged

    private void _okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__okActionPerformed
        if(_op != null)
            Implementor.Instance().adjust(_op);
        setVisible(false);
        dispose();
    }//GEN-LAST:event__okActionPerformed

    private void _cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__cancelActionPerformed
        setVisible(false);
        dispose();
    }//GEN-LAST:event__cancelActionPerformed

    private void _widthActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__widthActionPerformed
        _op = calculateOp();
        ((PreviewPane)_previewPane).setOp(_op);
    }//GEN-LAST:event__widthActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton _cancel;
    private javax.swing.JLabel _depthLabel;
    private javax.swing.JButton _ok;
    private javax.swing.JLabel _previewLabel;
    private javax.swing.JPanel _previewPane;
    private javax.swing.JSlider _slider;
    private javax.swing.JComboBox _width;
    private javax.swing.JLabel _widthLabel;
    // End of variables declaration//GEN-END:variables
    private ConvolveOp                  _op = null;
}
